import { connect } from 'dva';
import * as THREE from 'three'
import { useEffect, useRef } from 'react';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'

 const LightPage = (props) => {
   const sceneRef = useRef(null)
   const cameraRef = useRef(null)
   const rendererRef = useRef(null)
   const guiRef = useRef(null)
   const width = 1000; //宽度
   const height = 800; //高度
   useEffect(()=>{
    init()
   }, [])
   const init = () => {
      // 0.添加GUI
      const eventObj = {
        Fullscreen: function(){
         document.body.requestFullscreen()
        },
        Exitscreen: () => {
          document.exitFullscreen()
        }
      }
      guiRef.current = new GUI()
      guiRef.current.add(eventObj, "Fullscreen").name('全屏')
      guiRef.current.add(eventObj, "Exitscreen").name('退出全屏')

      // 1.创建3D场景对象Scene
      sceneRef.current = new THREE.Scene();

      // 4.创建物体
      setGeometry()

      // 2. 定义虚拟相机部分
      setCamera()

      // 5. 坐标辅助器
      const axesHelper = new THREE.AxesHelper(500)
      sceneRef.current.add(axesHelper)

      // 3.渲染器
      setRenderer()

      // 全屏 rendererRef.current.domElement.requestFullscreen()
      window.addEventListener("resize",()=>{
        rendererRef.current.setSize(window.innerWidth,window.innerHeight);
        cameraRef.current.aspect = window.innerWidth/window.innerHeight;
        cameraRef.current.updateProjectionMatrix()
      })

   }

   // 创建相机
   const setCamera = () => {
      // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
      cameraRef.current = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
      // 实例化一个透视投影相机对象
      // 根据需要设置相机位置具体值
      cameraRef.current.position.set(10, 10, 10);
      cameraRef.current.lookAt(0,0,0);//指向mesh对应的位置
   }
   // 创建几何体
   const setGeometry = () => {
      //  example 1：灯光
      getGeomery()   
   }
   // 创建渲染器
   const setRenderer = () => {
      // 创建渲染器对象
      rendererRef.current = new THREE.WebGLRenderer();
      rendererRef.current.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
      rendererRef.current.shadowMap.enabled = true; //开启阴影
      rendererRef.current.physicallyCorrectLights = true;//聚光灯decay
      rendererRef.current.render(sceneRef.current, cameraRef.current); //执行渲染操作
      document.getElementById('webgl').appendChild(rendererRef.current.domElement);
      // 6. 轨道控制器
      const controls = new OrbitControls(cameraRef.current, rendererRef.current.domElement)
     
      function animate(){
        requestAnimationFrame(animate)
        controls.update()
        rendererRef.current.render(sceneRef.current, cameraRef.current)
      }
      animate()
   }
   // 平面
   const getGeomery = () => {
     // 灯光
     // 1. 环境光 AmbientLight
     const ambientLight = new THREE.AmbientLight(0x00ff00, 1);
     sceneRef.current.add(ambientLight)
     // 2. 平行光 DirectionalLight
    //  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
    //  directionalLight.position.set(10,10,10);
    //  directionalLight.castShadow = true;
    //  // 设置阴影模糊度
    //  directionalLight.shadow.radius = 20;
    //  // 设置阴影分辨率，清楚点
    //  directionalLight.shadow.mapSize.set(2048, 2048)
    //  // 设置平行光投射相机的属性
    //  directionalLight.shadow.camera.near = 0.5;
    //  directionalLight.shadow.camera.far = 5000;
    //  directionalLight.shadow.camera.top = 5;
    //  directionalLight.shadow.camera.bottom = -5;
    //  directionalLight.shadow.camera.left = -5;
    //  directionalLight.shadow.camera.right = 5;

    //  sceneRef.current.add(directionalLight)
    //  guiRef.current.add(directionalLight.shadow.camera,"near")
    //  .min(0).max(20).step(0.1).onChange(()=>{
    //      directionalLight.shadow.camera.updateProjectionMatrix()
    //  })
    //  guiRef.current.add(directionalLight.shadow.camera,"far")
    //  .min(100).max(2000).step(10).onChange(()=>{
    //      directionalLight.shadow.camera.updateProjectionMatrix()
    //  })
    // 模拟灯泡（将点光源赋到一个小球上）
    const lightBall = new THREE.Mesh(
        new THREE.SphereGeometry(0.1,20,20),
        new THREE.MeshStandardMaterial({color: 0xff0000})
    )
    lightBall.position.set(2,2,2)
    
    // 3. 点光源 PointLight
     const pointLight = new THREE.PointLight(0xffffff, 1);
     pointLight.position.set(2,2,5)
     pointLight.castShadow = true;
     pointLight.shadow.radius = 20;
     pointLight.decay = 0

     lightBall.add(pointLight)
     sceneRef.current.add(lightBall)

     guiRef.current.add(pointLight,"distance").min(0).max(10).step(0.01)
     guiRef.current.add(pointLight,"decay").min(0).max(10).step(0.01)
    // 4. 聚光灯 SpotLight
    // const spotLight = new THREE.SpotLight(0xffffff, 0.5, 0, Math.PI/4);
    // spotLight.position.set(5,5,5)
    // spotLight.castShadow = true;
    // spotLight.decay = 0;
    // spotLight.shadow.mapSize.width = 2048;
    // spotLight.shadow.mapSize.height = 2048;
    // // 设置阴影模糊度
    // spotLight.shadow.radius = 20;
    // 设置透视投射相机的属性
    // spotLight.shadow.camera.near = 500;
    // spotLight.shadow.camera.far = 4000;
    // // spotLight.shadow.camera.fov = 30;
    // sceneRef.current.add(spotLight)
    // guiRef.current.add(spotLight,"angle").min(0).max(Math.PI/2).step(0.01)
    // guiRef.current.add(spotLight,"distance").min(0).max(10).step(0.01)
    // guiRef.current.add(spotLight,"penumbra").min(0).max(10).step(0.01)
    // guiRef.current.add(spotLight,"decay").min(0).max(10).step(0.01)

     // 创建几何体
     // 1. 创建个球
     const sphereGeometry = new THREE.SphereGeometry(1,20,20);
     const material = new THREE.MeshStandardMaterial()
     const sphere = new THREE.Mesh(sphereGeometry,material) 
     // 3. 物体 投射阴影
     sphere.castShadow = true;
     sceneRef.current.add(sphere) 
    //  spotLight.target = sphere;
     // 2. 创建平面
     const planeGeometry = new THREE.PlaneGeometry(20,20);
     const plane = new THREE.Mesh(planeGeometry,material)
     plane.position.set(0,-5,0);
     plane.rotation.x = -Math.PI/2;
     // 4. 平面 接收阴影
     plane.receiveShadow = true;
     sceneRef.current.add(plane)
    
    guiRef.current.add(sphere.position,"x")
     .min(-5).max(5).step(0.1)
    
   }

  return (
    <div>
      <h1>灯光、阴影</h1>
      <div id="webgl" style={{marginTop: 10,marginLeft: 10}}></div>
    </div>
  );
}
export default connect(({common})=>({
  userInfo: common.userInfo,
}))(LightPage)